﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IURIP;
using System.Xml;
using URIP.Tool;
using URIP.Factory;

namespace URIP.Core
{
    public class ActionTemplate : BaseTemplate, IActionTemplate
    {
        public ActionTemplate(ITarget target, ITemplate parentTemplate) :
            base(target, parentTemplate)
        {
        }

        private IFilter m_filter = new Filter();
        private IFilter m_recursiveFilter = new Filter();
        private string m_name = "";
        private string m_parentXPath = "/";
        private string m_referenceDataBlock = "";
        private bool m_isRecursive = false;
        private string m_recursiveReference = "";
        private string m_recursiveIdentifiedKey = "";

        public IFilter Filter
        {
            get { return m_filter; }
        }
        public IFilter RecursiveFilter
        {
            get { return m_recursiveFilter; }
        }
        public string Name
        {
            get { return m_name; }
        }
        public string ParentXPath
        {
            get { return m_parentXPath; }
        }
        public string ReferenceDataBlock
        {
            get { return m_referenceDataBlock; }
        }
        public bool IsRecursive
        {
            get { return m_isRecursive; }
        }
        public string RecursiveReference
        {
            get { return m_recursiveReference; }
        }
        public string RecursiveIdentifiedKey
        {
            get { return m_recursiveIdentifiedKey; }
        }

        public override IRunable CreateRunable(IRunable parentRunable)
        {
            var res = new Action(this, parentRunable);
            return res;
        }
        public override void InitByConfiguration(XmlNode node)
        {
            this.m_name = Util.GetAttributeValue(node, "name", true);
            if (string.IsNullOrEmpty(m_name))
            {
                throw new Exception(string.Format("There is an action item with invalid name attribute. All action items should have unique name."));
            }
            if (ProcessTemplate != null && ProcessTemplate.ActionTemplates.ContainsKey(Name))
            {
                throw new Exception(string.Format("The action name {0} is repeated in target {1}!", Name, Target.Name));
            }
            else if (ProcessTemplate != null)
            {
                ProcessTemplate.ActionTemplates.Add(Name, this);
            }
            this.m_parentXPath = Util.GetAttributeValue(node, "parentPath", true);
            this.m_referenceDataBlock = Util.GetAttributeValue(node, "referenceDataBlock", true);
            if (!Target.DataBlocks.ContainsKey(this.m_referenceDataBlock))
            {
                throw new Exception(string.Format("The data block {0} used in action {1} is not defined ", m_referenceDataBlock, m_name));
            }
            this.m_recursiveReference = Util.GetAttributeValue(node, "recursiveReference", true);
            this.m_recursiveIdentifiedKey = Util.GetAttributeValue(node, "recursiveIdentifiedKey", true);
            this.m_isRecursive = Util.GetAttributeBoolValue(node, "isRecursive", true);
            XmlNode filterNode = Util.GetXPathNode(node, "./query");
            if (filterNode != null)
            {
                m_filter.Query = filterNode.InnerXml;
            }
            XmlNode recursiveFilterNode = Util.GetXPathNode(node, "./recursiveQuery");
            if (recursiveFilterNode != null)
            {
                m_recursiveFilter.Query = recursiveFilterNode.InnerXml;
            }

            if (node.HasChildNodes)
            {
                var tmpNode = node.FirstChild;
                while (tmpNode != null)
                {
                    if (tmpNode.Name == "Action")
                    {
                        var template = new ActionTemplate(Target, this);
                        template.InitByConfiguration(tmpNode);
                        ChildrenTemplates.AddLast(template);
                        Task.Logger.LogInfo("Finish loading ActionTemplate {0}.", template.Name);
                    }
                    else if (tmpNode.Name == "Rule")
                    {
                        var template = RuleTemplateFactory.GetRuleTemplate(tmpNode, Target, this);
                        ChildrenTemplates.AddLast(template);
                        Task.Logger.LogInfo("Finish loading Rule {0}.", template.Name);
                    }
                    tmpNode = tmpNode.NextSibling;
                }
            }
        }
    }
}
